/* eslint-disable prettier/prettier */
/**
 * @Author: Bobby
 * @Date: 2021-11-08 15:22:12
 * @LastEditTime: 2022-03-23 09:16:13
 * @LastEditors: Bobby
 * @Description:
 * @FilePath: \wms-v2\src\utils\request.js
 * @CIMC-V2
 */
import axios from 'axios'
import { contentType, debounce, messageName, requestTimeout, statusName, successCode, requestEncryptd } from '@project/config'

import store from '@commonProject/store'
import qs from 'qs'
import router from '@commonProject/router'
import { isArray } from '@/utils/validate'
import { decryptd, encryptd } from '@/utils/tools'
import { addErrorLog, needErrorLog } from '@/vui/plugins/common/errorLog'
import { gp } from '@vui'
import { getUrlSystemApp } from '@/utils/tools'

let loadingInstance
const getQuery = (query) => {
  if (typeof query === 'string') {
    const arr = query.split('&')
    const result = {}
    for (let i = 0; i < arr.length; i++) {
      const [key, value] = arr[i].split('=')
      result[key] = value
    }
    return result
  }
  return query
}
//忽略加密解密的method
const neglectEncryptMethod = [
  'roleServiceImpl.queryUserRolePageJson',
  'sysPageServiceImpl.standardSavePageJson',
  'dams.mongodb.history.config.query',
  'page.config.mongodb.history',
  'sysPageServiceImpl.queryLanguageForPage',
  'roleServiceImpl.queryRolePageJson',
  'roleServiceImpl.saveRolePageJson',
  'sysPageServiceImpl.saveTranslationPageJson',
  'sysPageServiceImpl.standardQueryPageJson',
]
const neglectUrl = ['apim/log/query', '/apim/config']
// 操作正常Code数组
const codeVerificationArray = isArray(successCode) ? [...successCode] : [...[successCode]]

const CODE_MESSAGE = {
  200: '服务器成功返回请求数据',
  201: '新建或修改数据成功',
  202: '一个请求已经进入后台排队(异步任务)',
  204: '删除数据成功',
  400: '发出信息有误',
  401: '用户没有权限(令牌失效、用户名、密码错误、登录过期)',
  402: '令牌过期',
  403: '用户得到授权，但是访问是被禁止的',
  404: '访问资源不存在',
  406: '请求格式不可得',
  410: '请求资源被永久删除，且不会被看到',
  500: '服务器发生错误',
  502: '网关错误',
  503: '服务不可用，服务器暂时过载或维护',
  504: '网关超时',
}

/**
 * axios响应拦截器
 * @param config 请求配置
 * @param data response数据
 * @param status HTTP status
 * @param statusText HTTP status text
 * @returns {Promise<*|*>}
 */
const handleData = async ({ config, data, status, statusText, headers }) => {
  if (loadingInstance) loadingInstance.close()
  // console.log('data:', data)
  // 若data.code存在，覆盖默认code
  let code = data && data[statusName] ? data[statusName] : status
  // 若code属于操作正常code，则status修改为200
  if (data && codeVerificationArray.indexOf(data[statusName]) + 1) code = 200

  //退出
  if (['S0000', 'S0001', 'S0003', 'S0007', 401].includes(code)) {
    console.log('调用resetAll -1')
    await store.dispatch('user/resetAll', {
      clear: false,
      toLoginUrl: true,
    })
    return
  }
  switch (code) {
    case 200:
      // 业务层级错误处理，以下是假定restful有一套统一输出格式(指不管成功与否都有相应的数据格式)情况下进行处理
      // 例如响应内容：
      // 错误内容：{ code: 1, msg: '非法参数' }
      // 正确内容：{ code: 200, data: {  }, msg: '操作正常' }
      if (config.responseType == 'blob' && config.data.indexOf('flag') > -1 && headers['content-disposition']) {
        return { data: data, disposition: headers['content-disposition'] }
      } else {
        //下载不需要解密
        if (headers['content-disposition'] || neglectUrl.find((el) => config.url.indexOf(el) > -1)) {
          return data
        }
        const dataQuery = getQuery(config.data)
        return requestEncryptd && neglectEncryptMethod.indexOf(dataQuery.method) === -1 ? JSON.parse(decryptd(decodeURIComponent(data))) : data
      }
    case 403:
      router.push({ path: '/403' }).then(() => {
        console.log(111)
      })
      break
  }
  let msgData
  if (neglectUrl.find((el) => config.url.indexOf(el) > -1)) {
    msgData = data
  } else {
    msgData = requestEncryptd && neglectEncryptMethod.indexOf(config.data.method) === -1 ? JSON.parse(decryptd(decodeURIComponent(data))) : data
  }
  // const msgData = requestEncryptd && neglectEncryptMethod.indexOf(config.data.method) === -1 ? JSON.parse(decryptd(decodeURIComponent(data))) : data
  // 异常处理
  // 若data.msg存在，覆盖默认提醒消息
  const errMsg = `${msgData && msgData[messageName] ? msgData[messageName] : CODE_MESSAGE[code] ? CODE_MESSAGE[code] : statusText}`
  // 是否显示高亮错误(与errorHandler钩子触发逻辑一致)
  // console.log('errMsg', errMsg, data)
  // console.log('config ---------------- ', config)
  if (!config.notOpenMessage) {
    const ApiLogPath = store.getters['fileConfig/data']['common']['ApiLogPath'] || ''
    // gp.$baseMessage(
    //   `
    //   <div class="w-80 overflow-x-hidden overflow-y-scroll scrollbar--light " style="min-height:70px;max-height:200px;">
    //   <div class="text-xs text-gray-400 mb-2 break-words">
    //     <a href="${ApiLogPath}?REQUEST_UUID=${data.logid}">${data.code}:${data.logid}</a>
    //   </div>
    //   <div>${errMsg}</div>
    // </div>
    // `,
    //   'error',
    //   'vui-hey-message-error',
    //   true
    // )
    let vt = gp.$vuiToast(
      `
    <div class="flex" style="background: #fff4f1;padding: 14px;border-radius: 4px;max-width:900px;min-width400px;">
      <div class="mr-2"><svg t="1657612932040" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="17386" width="30" height="30"><path d="M512 1024C229.248 1024 0 794.752 0 512S229.248 0 512 0s512 229.248 512 512-229.248 512-512 512z m0-572.330667L300.629333 240.213333a42.538667 42.538667 0 0 0-60.16 0.213334 42.410667 42.410667 0 0 0-0.213333 60.16L451.669333 512 240.213333 723.370667a42.538667 42.538667 0 0 0 0.213334 60.16 42.410667 42.410667 0 0 0 60.16 0.213333L512 572.330667l211.370667 211.413333a42.538667 42.538667 0 0 0 60.16-0.213333 42.410667 42.410667 0 0 0 0.213333-60.16L572.330667 512l211.413333-211.370667a42.538667 42.538667 0 0 0-0.213333-60.16 42.410667 42.410667 0 0 0-60.16-0.213333L512 451.669333z" fill="#FC675E" p-id="17387"></path></svg></div>
      <div class="text-xs text-gray-400 mb-2 break-words" style="color:#666666;">
          <div class="flex mb-2">
            <span style="width: 64px;display: inline-block;text-align: right;">错误代码:</span>
            <span class="flex-1">${data.code}</span>
          </div>
          <div class="flex">
            <span style="width: 64px;display: inline-block;text-align: right;">日志ID:</span>
            <a class="flex-1 open-log-btn" style="text-decoration:underline;cursor: pointer;"  data-href="${ApiLogPath}?systemApp=${getUrlSystemApp()}&REQUEST_UUID=${data.logid
      }">${data.code}:${data.logid}</a>
          </div>
      </div>
    </div>
    <div style="background: #f5f7fb;border-radius: 4px;padding:10px;font-weight: 502;margin-top:8px;">错误信息${data.message ? data.message : ''
      }</div>
    <div style="padding: 0 10px;border: 1px solid #f5f7fb;max-height:200px" class="overflow-x-hidden overflow-y-scroll scrollbar--light " style="min-height:70px;max-height:200px;">
      <div style="line-height: 1.6;">${errMsg}</div>
    </div>
      `,
      'warning'
    )

    document.querySelector('.open-log-btn') &&
      (document.querySelector('.open-log-btn').onclick = () => {
        vt.close()
        if (store.getters['user/appCode'] == 'DAMS') {
          window.open(`${ApiLogPath}?systemApp=${getUrlSystemApp()}&REQUEST_UUID=${data.logid}`)
        } else {
          router.push({ path: ApiLogPath, query: { systemApp: getUrlSystemApp(), REQUEST_UUID: data.logid } })
        }
      })
  }

  if (config.baseMessage === true) {
    gp.$baseMessage(errMsg, `error`)
  }

  if (needErrorLog()) addErrorLog({ message: errMsg, stack: data, isRequest: true })
  return Promise.reject(data)
}

/**
 * @description axios初始化
 */
const instance = axios.create({
  // baseURL,
  timeout: requestTimeout,
  headers: {
    'Content-Type': contentType,
  },
})

/**
 * @description axios请求拦截器
 */
instance.interceptors.request.use(
  (config) => {
    const token = config.data.token ? config.data.token : store.getters['user/token']
    // body data str
    const dataToStr = config.dataToStr == false ? false : true
    // console.log('request', config)
    // 规范写法 不可随意自定义
    if (token) config.headers['token'] = `${token}`
    function hasCn(key, value) {
      var reg = /[\u4E00-\u9FA5]|[\uFE30-\uFFA0]/g
      if (reg.test(value)) {
        gp.$baseMessage(`Headers ${key} 不能是中文`, 'error', 'vui-hey-message-error')
        return ''
      } else {
        return value
      }
    }
    config.headers['finger-mark'] = store.getters['tmp/getFingerprint']

    config.headers['warehouse-id'] = hasCn('wareHoseId', store.getters['user/wareHoseId'])
    config.headers['app-code'] = hasCn('appCode', store.getters['user/appCode'])
    config.headers['menu-code'] = hasCn(
      'menuCode',
      store.getters['tmp/getNowMenuCode'] == undefined || store.getters['tmp/getNowMenuCode'] == 'undefined'
        ? ''
        : store.getters['tmp/getNowMenuCode']
    )
    config.headers['button-id'] = hasCn('buttonId', store.getters['tmp/getButtonId']) //`${#BUTTON_ID#}`
    // console.log('config.headers', config.headers)
    if (config.data && config.headers['Content-Type'] === 'application/x-www-form-urlencoded') {
      if (requestEncryptd && neglectEncryptMethod.indexOf(config.data.method) === -1 && neglectUrl.find((el) => config.url.indexOf(el) == -1)) {
        config.data.data = encryptd(config.data.data)
      }
      config.data = dataToStr ? qs.stringify(config.data) : config.data
    }
    if (debounce.some((item) => config.url.includes(item))) {
      loadingInstance = gp.$baseLoading()
    }

    return config
  },
  (error) => {
    return Promise.reject(error)
  }
)

/**
 * @description axios响应拦截器
 */
instance.interceptors.response.use(
  (response) => handleData(response),
  (error) => {
    console.log('error', error)
    const { response } = error
    if (response === undefined) {
      if (loadingInstance) loadingInstance.close()
      gp.$baseMessage('未可知错误，可能是因为后端不支持跨域CORS、接口地址不存在等问题引起', 'error', 'vui-hey-message-error')
      return {}
    } else return handleData(response)
  }
)

export default instance
